M33: Snake & MountainCar AI run fully in the browser (zero server inference)#24
Merged
Conversation
…glot 0.1.4->0.3.0 3-agent investigation + Polyglot 0.3.0 verification. 0.3.0 fixes all of #11 (transcendentals added, module imports now link, i32() TS wrap fixed) and #9 stays fixed — so MountainCar's transcendental fork dissolves (cos/tanh writable in a .pg; sub-ULP C#<->TS drift harmless post-cutover). FruitCake TS codegen verified content-identical on 0.3.0 (22 tests green). Filed remaining gaps as MintPlayer.Polyglot#11 (all addressed in 0.3.0). Plan: Snake first (clean full-Polyglot port), MountainCar second (now also uniform Polyglot). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ntPlayer.Polyglot#14 snake_solver.pg ports SnakeEnv (dynamics + 177-dim observation + action mask incl. the anti-self-trap flood-fill shield) over flat Lists (body head-at-end, occupancy bool-list, BFS via list+cursor — no HashSet/LinkedList/Queue), plus PgDuelingNet + a masked-greedy chooseAction. It type-checks and generates correct C#/TS individually. BLOCKED from building alongside FruitCake by MintPlayer.Polyglot#14: with a 2nd .pg each transpiled .cs re-emits the prelude (Option/Some/None) → CS0101. Parked via PolyglotFile Remove so the branch stays green; delete the Remove + continue (facade/tests/director) once the prelude is deduped upstream. Env build green with Snake excluded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…longside FruitCake Bump 0.3.0->0.3.1 (shared __polyglot_prelude.cs + partial PolyglotProgram fix #14), drop the PolyglotFile Remove workaround. Fixes to snake_solver.pg: rename PgDuelingNet->PgSnakeNet (distinct name; a deliberate copy of FruitCake's net — one assembly, so a shared name would clash; a shared nn.pg is a future refactor), and rename a fill-loop var to avoid a C# i-scope clash (CS0136). Environments builds with both .pg; 22 FruitCake/Polyglot tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… (SN1-SN3) Rewrite the C# SnakeEnv to delegate to the transpiled PgSnakeEnv (dynamics + 177-dim observation + action mask incl. the flood-fill shield now live once in snake_solver.pg, shared with the browser's generated snake_solver.ts). The facade re-adds host concerns: IEnvironment/IStatefulEnvironment API, the food RNG (Xoshiro, kept out of the single source via the core's needsFood signal so determinism holds), the head-first Body/state format, and the throw-on-illegal-action contract. Also commit the generated snake_solver.ts. All 9 SnakeEnvTests green (dynamics, tail-follow occupancy sync, eating/wall/mask/throw, same-seed obs, save/restore round-trip); Occupied() helper updated to read the core's occupancy list. Full solution builds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… retire server SN4: ship the 177-dim net as ClientApp/public/snake-net.ckpt (LFS) + snake-net.ts parser (builds PgSnakeNet from the dueling-q checkpoint). SN5: SnakeDirector runs the whole AI in the browser — PgSnakeEnv dynamics + the flood-fill action mask + masked-greedy chooseAction over the loaded net, on a discrete tick. Rewire the Snake component's watch mode to it (drop the WebSocket/SnakeApi); both modes now run in-browser. SN6: delete SnakeController, SnakeModelService (+ Program.cs regs), snake-api.ts, the stale models/snake.dqn.ckpt, and SnakeApiTests (server WS/status path). EpisodeStreamer kept (MountainCar still uses it). Web builds; 32 Snake/FruitCake/Polyglot tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ny TS7022) The BFS queue (List<i32> whose pushed values derive from reading the same list) transpiled to an untyped `let queue = []` with circular element inference -> TS7022 in the browser build. Rewrite reachableFreeSpace as iterative relaxation over the `seen` bool-list (BFS-equivalent; values come from a fixed 0..cells range, never a list read). Snake grids are small so O(cells^2) is fine. C# + TS regen; 9 SnakeEnvTests green (obs/mask unchanged). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Snake ships fully client-side (branch snake-clientside-ai): env+obs+mask+net single-sourced in snake_solver.pg, C# SnakeEnv facade, browser director, server path retired. Verified in browser (AI ate 40 / length ~35, 0 console errors, 0 /api/snake calls). MountainCar remains (now uniform-Polyglot since 0.3.0 added cos/tanh). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…lot, retire server mountaincar_solver.pg single-sources the classic-control dynamics (cos), the normalised 2-dim observation, and the PPO policy forward (PgMlpNet: Linear+Tanh hidden, linear output, argmax) — cos/tanh now available in Polyglot 0.3.0+ (sub-ULP C#<->TS drift is harmless: no server twin, argmax decision; C# stays exact via Math.Cos). C# MountainCarEnv is a facade over PgMountainCarEnv (6 MountainCarEnvTests green, incl. the Gymnasium golden dynamics). Browser: ship models/mountaincar.ppo.ckpt -> public/mountaincar-net.ckpt (LFS) + a mlp .ckpt parser (mountaincar-net.ts -> PgMlpNet) + MountainCarDirector; rewire the watch mode off the WebSocket. Retire the server path: MountainCarController, MountainCarModelService (+ Program.cs regs), mountaincar-api.ts, stale net, MountainCarApiTests, and EpisodeStreamer (now unused). Removed app.UseWebSockets() — no server WS remains (all games client-side). Web builds; 38 env/Polyglot tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ainCar) Both remaining WebSocket-AI games now run entirely in the browser; no server WebSocket remains anywhere (EpisodeStreamer + UseWebSockets removed). Verified in-browser (Snake ate 40; MountainCar reaches the flag). PRD status -> IMPLEMENTED; PLAN M33 both games done. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Extends the FruitCake M32 pattern to the two remaining WebSocket-AI games. After this, no game's "watch AI" touches the server — every one runs client-side, and there is no server WebSocket left in the app.
What's in here
snake_solver.pgsingle-sources the dynamics + 177-dim egocentric observation + the action mask including the anti-self-trap flood-fill shield +PgSnakeNet+ a masked-greedychooseAction. C#SnakeEnvis now a facade over it. Browser:snake-net.ckpt+snake-net.tsparser +SnakeDirector.mountaincar_solver.pgsingle-sources the classic-control dynamics (cos) + normalised 2-dim observation + the PPO policyPgMlpNet(Linear+Tanh hidden, linear output, argmax). C#MountainCarEnvis a facade. Browser:mountaincar-net.ckpt+mountaincar-net.ts(parseMlp) +MountainCarDirector.Program.csregs), the two*-api.tssocket clients, the stalemodels/*.ckpt, the API tests, the sharedEpisodeStreamer, andapp.UseWebSockets()— all removed. The only server AI surfaces left are the request/response REST solvers (2048/RushHour/Cube).Why it matters
Per-viewer server inference/streaming for Snake + MountainCar → zero (a one-time, CDN-cached weights download each). Combined with M32 (FruitCake), the whole playground's live "watch AI" is now client-side.
Design notes
.pg(transpiled to C# at build + committed TS), so the C# training/eval env and the browser share one source. C# facades re-add host concerns (theIEnvironmentAPI, the food/start RNG kept host-side for determinism, state I/O, the throw-on-illegal-action contract).cos/tanh(Polyglot 0.3.0+); the C# side stays exact (Math.Cos), the browser differs by ≤1 ULP which is harmless (argmax decision, no server twin).PgSnakeNet= a renamed copy of FruitCake's dueling net;PgMlpNetnew) rather than a sharednn.pg— fine for two games.Verification
/…-net.ckpt, 0/api/{snake,mountaincar}calls.lfs: truecheckout + DockerfileCOPY ClientApp/beforenpm build; Angular servespublic/**).Upstream (MintPlayer.Polyglot)
Bumped 0.1.4 → 0.3.1. Filed and got fixed: #11 (transcendentals + module linking +
i32()wrap, in 0.3.0) and #14 (multi-.pgprelude collision, in 0.3.1). Worked around a net-agnostic evolving-any TS7022 (Snake BFS → relaxation).Test plan
dotnet testenv + Polyglot filter (38 green)/api/*AI calls🤖 Generated with Claude Code